package com.bingxue.edu.management.system.service;

import com.bingxue.edu.framework.config.DynamicConfigRefresher;
import com.bingxue.edu.framework.mybatis.base.BaseService;
import com.bingxue.edu.management.system.mapper.ConfigMapper;
import com.bingxue.edu.management.system.model.entity.Config;
import com.bingxue.edu.management.system.model.req.ConfigReq;
import com.bingxue.edu.management.system.model.resp.ConfigCategoryResp;
import com.mybatisflex.core.query.QueryMethods;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.bingxue.edu.management.system.model.entity.table.ConfigTableDef.CONFIG;


/**
 * 配置业务实现
 *
 * @author panbo
 * @since 2024/07/09 19:52
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ConfigService extends BaseService<ConfigMapper, Config> {

    private final DynamicConfigRefresher dynamicConfigRefresher;

    /**
     * 根据类别查询配置列表
     * @param category 类别
     * @return 配置列表
     */
    public List<Config> listByCategory(String category) {
        return this.queryChain().where(CONFIG.CATEGORY.eq(category)).list();
    }

    /**
     * 根据类别查询配置map
     * @param category 类别
     * @return 配置map
     */
    public Map<String, Object> listMapByCategory(String category) {
        List<Config> configList = this.queryChain().where(CONFIG.CATEGORY.eq(category)).list();
        return toConfigMap(configList);
    }

    /**
     * 查询支持动态配置的配置map
     * @return 动态配置map
     */
    public Map<String, Object> listDynamicConfigMap() {
        List<Config> configList = this.queryChain().where(CONFIG.DYNAMIC.eq(true)).list();
        return toConfigMap(configList);
    }

    /**
     * 更新配置
     * @param code 配置code
     * @param value 配置值
     */
    public void updateConfig(String code, String value) {
        boolean updated = this.updateChain().set(CONFIG.VALUE, value).where(CONFIG.CODE.eq(code)).update();
        dynamicConfigRefresher.refresh(Map.of(code, value));
        log.info("更新系统配置成功, code:{}, value:{}", code, value);
    }

    /**
     * 更新配置
     * @param configMap 配置map
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateConfigMap(Map<String, Object> configMap) {
        HashMap<String, Object> changedConfigMap = new HashMap<>();
        configMap.forEach((code, value) -> {
            boolean updated = this.updateChain().set(CONFIG.VALUE, value).where(CONFIG.CODE.eq(code)).update();
            if (updated) {
                changedConfigMap.put(code, value);
            }
        });
        dynamicConfigRefresher.refresh(changedConfigMap);
        log.info("更新系统配置成功");
    }

    /**
     * 更新单个配置
     */
    public void updateConfig(ConfigReq req, String id) {
        Config config = this.copyById(req, id);
        this.updateById(config);
        Map<String, Object> changedConfigMap = Map.of(req.getCode(), req.getValue());
        dynamicConfigRefresher.refresh(changedConfigMap);
        log.info("更新单个系统配置成功, {}", req);
    }

    /**
     * 查询配置类别
     * @return 配置类别
     */
    public List<ConfigCategoryResp> listCategory() {
        return this.queryChain()
                .select((CONFIG.CATEGORY), QueryMethods.count().as(ConfigCategoryResp::getConfigCount))
                .groupBy(CONFIG.CATEGORY)
                .listAs(ConfigCategoryResp.class);
    }

    /**
     * 将配置列表转换为配置map，key为code，value为配置值
     * @param configList 配置列表
     * @return 配置map
     */
    protected Map<String, Object> toConfigMap(List<Config> configList) {
        return configList.stream().collect(Collectors.toMap(Config::getCode, Config::getValue));
    }

}
